Skip to content

Revert "fix: marker series issue rebuild"#481

Merged
behnam-deriv merged 1 commit into
masterfrom
revert-476-fix-marker-rebuild-issue
Jun 19, 2026
Merged

Revert "fix: marker series issue rebuild"#481
behnam-deriv merged 1 commit into
masterfrom
revert-476-fix-marker-rebuild-issue

Conversation

@behnam-deriv

@behnam-deriv behnam-deriv commented Jun 19, 2026

Copy link
Copy Markdown
Collaborator

Reverts #476

Summary by Sourcery

Revert the previous change that forced marker series widgets to remount when marker data changed, restoring the original marker area build behavior.

@sourcery-ai

sourcery-ai Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor
Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Reverts the previous fix that forced marker-related widgets to remount when markerSeries changed, restoring the earlier, simpler widget structure for the marker area and main chart layout.

File-Level Changes

Change Details Files
Remove ObjectKey-based remounting behavior tied to markerSeries from the main chart LayoutBuilder.
  • Drop the ObjectKey keyed by markerSeries from the LayoutBuilder in the main chart build method so the widget is no longer forced to remount on markerSeries changes.
  • Restore the previous behavior where the LayoutBuilder rebuilds only on constraint changes rather than markerSeries identity changes.
lib/src/deriv_chart/chart/main_chart.dart
Simplify marker area construction by removing the KeyedSubtree wrapper around MarkerArea.
  • Replace the KeyedSubtree keyed by markerSeries with a direct MultipleAnimatedBuilder for the marker area.
  • Keep the existing animations and MarkerArea configuration while removing the additional key-based remounting layer.
lib/src/deriv_chart/chart/main_chart.dart

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@github-actions

Copy link
Copy Markdown

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

OpenSSF Scorecard

PackageVersionScoreDetails

Scanned Manifest Files

@claude

claude Bot commented Jun 19, 2026

Copy link
Copy Markdown

Claude finished @behnam-deriv's task —— View job


Code Review Complete

Tasks

  • Read the changed file and understand the revert
  • Review git diff to see exact changes
  • Investigate MarkerArea and MarkerSeries to understand rebuild behavior
  • Analyze potential regressions and edge cases
  • Provide comprehensive review feedback

Summary

This PR reverts the fix from #476 which added ObjectKey-based remounting for marker-related widgets. While the revert simplifies the code, it likely reintroduces the original bug that #476 was designed to fix.

Critical Issues (High Priority)

1. Potential Regression: MarkerArea State Persistence Bug

Location: lib/src/deriv_chart/chart/main_chart.dart:582-595

Issue: The original PR #476 added explicit keying to force widget remounting when markerSeries changes. The commit message stated:

"LayoutBuilder only re-invokes its builder on constraint changes; without a key that tracks markerSeries identity, the old MarkerArea subtree persists after trade-type switches."

By removing both:

  1. ObjectKey(widget.markerSeries) from the LayoutBuilder (line 401)
  2. KeyedSubtree wrapper with ObjectKey(widget.markerSeries) from _buildMarkerArea() (line 582)

The widget tree may not properly rebuild when switching between different marker series instances, particularly during trade-type changes.

Root Cause Analysis:

Looking at marker_area.dart:41-57, the _MarkerAreaState has stateful behavior:

  • gestureManager is registered in initState() with a callback: gestureManager.registerCallback(_onTap)
  • The callback is removed in dispose(): gestureManager.removeCallback(_onTap)

When markerSeries changes identity but the widget doesn't remount:

  • The old _MarkerAreaState instance persists
  • The old gesture callbacks remain registered
  • The widget continues to reference the old markerSeries in its closure context
  • This can lead to stale tap handlers and incorrect marker interactions

Evidence from code:

// marker_area.dart:59-69
void _onTap(TapUpDetails details) {
  final MarkerSeries series = widget.markerSeries; // <-- References current widget's series
  
  if (series.activeMarker != null) {
    if (series.activeMarker!.tapArea.contains(details.localPosition)) {
      series.activeMarker!.onTap?.call();
    } else {
      series.activeMarker!.onTapOutside?.call();
    }
    return;
  }
  // ...
}

While the build() method calls widget.markerSeries.update() on each rebuild, the gesture callback registration happens only once in initState(), which means the callback closure may capture stale references.

Impact:

  • Medium-High severity: Trade type switches may result in incorrect marker behavior
  • Users tapping markers after a trade type change might trigger callbacks for the wrong series
  • Visual inconsistencies between displayed markers and interactive tap areas

Recommendation:

  • Do not merge this revert without first understanding why the original issue occurred
  • 🔍 Investigate the root cause: Why does markerSeries change identity during trade-type switches?
  • 🎯 Consider a better fix:
    • Override didUpdateWidget() in _MarkerAreaState to re-register callbacks when markerSeries changes
    • Use a more stable identity for markerSeries so it doesn't change on every rebuild
    • Add proper equality checks to avoid unnecessary remounting

Medium Priority Issues

2. Missing Test Coverage

Issue: There are no automated tests for marker rebuild behavior. This makes it:

  • Difficult to verify the original bug exists
  • Impossible to prevent regressions
  • Hard to validate alternative fixes

Recommendation:

  • Add widget tests that verify correct behavior when markerSeries changes
  • Test gesture callback behavior after marker series updates
  • Consider integration tests for trade-type switching scenarios

3. Unclear Justification for Revert

Issue: The PR description only states "Reverts #476" without explaining:

  • Why the original fix was problematic
  • What alternative solution is planned
  • Whether the original issue has been verified as non-existent

Recommendation:

  • Document in the PR description why the revert is necessary
  • Explain what problems the original fix caused (performance, bugs, architecture concerns)
  • Outline a plan for addressing the original issue differently

Low Priority Issues

4. Code Comments Removed

Location: lib/src/deriv_chart/chart/main_chart.dart:401

The original fix included helpful documentation:

// Force remount when markerSeries changes.
// LayoutBuilder only re-invokes its builder on constraint changes;
// without a key that tracks markerSeries identity, the old
// MarkerArea subtree persists after trade-type switches.

Impact: Future developers lose context about this subtle Flutter framework behavior.

Recommendation: If the revert is necessary, consider adding a comment explaining why keying is NOT needed in this case.

Alternative Solutions to Consider

Instead of reverting, consider these approaches:

  1. Lifecycle-based callback management:
@override
void didUpdateWidget(MarkerArea oldWidget) {
  super.didUpdateWidget(oldWidget);
  if (oldWidget.markerSeries != widget.markerSeries) {
    gestureManager
      ..removeCallback(_onTap)
      ..registerCallback(_onTap);
  }
}
  1. Stable series identity: Ensure markerSeries maintains the same instance identity unless truly changing, using proper equality checks upstream.

  2. ValueKey instead of ObjectKey: If only certain properties matter, use ValueKey(widget.markerSeries.id) for more predictable behavior.

Testing Recommendations

Before merging, please verify:

  1. ✅ Trade type switching works correctly and markers respond to taps properly
  2. ✅ Marker tap callbacks invoke the correct handlers after trade type changes
  3. ✅ Active marker highlighting works correctly after series updates
  4. ✅ No memory leaks from unreleased gesture callbacks

Conclusion

RECOMMENDATION: Do not merge without further investigation.

While code simplification is valuable, this revert appears to reintroduce a real bug related to stateful widget lifecycle management. The original fix may have been crude (forcing remounting), but it addressed a legitimate issue with gesture callback staleness.

I recommend:

  1. Reproduce the original bug to confirm it exists
  2. Implement a more surgical fix using didUpdateWidget()
  3. Add test coverage to prevent future regressions
  4. Document the reasoning in code comments

@behnam-deriv

Copy link
Copy Markdown
Collaborator Author

Reverting this since it breaks the drawing tools functionality on web

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've left some high level feedback:

  • This revert removes the ObjectKey-based remount behavior for markerSeries; if the original change was addressing stale MarkerArea state on trade-type/series switches, it might be worth confirming whether you can keep a more targeted key (e.g., only on MarkerArea/KeyedSubtree) instead of fully reverting to avoid reintroducing that UI inconsistency.
  • Since LayoutBuilder is now unkeyed again, markerSeries identity changes will no longer trigger subtree reconstruction; if the revert is meant to fix a specific regression (e.g., performance or unwanted rebuilds), consider documenting that reasoning in the commit message to clarify why the original behavior is preferred.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- This revert removes the ObjectKey-based remount behavior for markerSeries; if the original change was addressing stale MarkerArea state on trade-type/series switches, it might be worth confirming whether you can keep a more targeted key (e.g., only on MarkerArea/KeyedSubtree) instead of fully reverting to avoid reintroducing that UI inconsistency.
- Since LayoutBuilder is now unkeyed again, markerSeries identity changes will no longer trigger subtree reconstruction; if the revert is meant to fix a specific regression (e.g., performance or unwanted rebuilds), consider documenting that reasoning in the commit message to clarify why the original behavior is preferred.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@behnam-deriv behnam-deriv merged commit bde802a into master Jun 19, 2026
6 of 8 checks passed
@behnam-deriv behnam-deriv deleted the revert-476-fix-marker-rebuild-issue branch June 19, 2026 08:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant